﻿using System;
using System.IO;
using System.Diagnostics;

namespace PickGold.Data.Hsts.General.Persist
{
	public class DateTimeIndexerPersist : IIndexerPersist<DateTime>
	{
		public const byte VERSION = 40;

		private static readonly long MILLISECOND = 10000;
		private static readonly long SECOND = 1000 * MILLISECOND;
		private static readonly long MINUTE = 60 * SECOND;
		private static readonly long HOUR = 60 * MINUTE;
		private static readonly long DAY = 24 * HOUR;

		private readonly Int64IndexerPersist persist = new Int64IndexerPersist(new long[] { MILLISECOND, SECOND, MINUTE, HOUR, DAY });

		public void Store(BinaryWriter writer, Func<int, object, DateTime> values, int count, object state)
		{
			writer.Write(VERSION);

			persist.Store(writer, (i, o) => values(i, o).Ticks, count, state);
		}

		public void Load(BinaryReader reader, Action<int, object, DateTime> values, int count, object state)
		{
			if (reader.ReadByte() != VERSION)
				throw new Exception("Invalid DateTimeIndexerPersist version.");

			persist.Load(reader, (i, o, v) => values(i, o, new DateTime(v)), count, state);
		}
	}

	public class TimeSpanIndexerPersist : IIndexerPersist<TimeSpan>
	{
		public const byte VERSION = 40;

		private static readonly long MILLISECOND = 10000L;
		private static readonly long SECOND = 1000L * MILLISECOND;
		private static readonly long MINUTE = 60L * SECOND;
		private static readonly long HOUR = 60L * MINUTE;
		private static readonly long DAY = 24L * HOUR;

		private readonly Int64IndexerPersist persist = new Int64IndexerPersist(new long[] { MILLISECOND, SECOND, MINUTE, HOUR, DAY });

		public void Store(BinaryWriter writer, Func<int, object, TimeSpan> values, int count, object state)
		{
			writer.Write(VERSION);

			persist.Store(writer, (i, o) => values(i, o).Ticks, count, state);
		}

		public void Load(BinaryReader reader, Action<int, object, TimeSpan> values, int count, object state)
		{
			if (reader.ReadByte() != VERSION)
				throw new Exception("Invalid DateTimeIndexerPersist version.");

			persist.Load(reader, (i, o, v) => values(i, o, new TimeSpan(v)), count, state);
		}
	}
}
